﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;

namespace NetTopologySuite.Planargraph
{
	public abstract class PlanarGraph
	{
		public Node FindNode(Coordinate pt)
		{
			return this.nodeMap.Find(pt);
		}

		protected void Add(Node node)
		{
			this.nodeMap.Add(node);
		}

		protected void Add(Edge edge)
		{
			this._edges.Add(edge);
			this.Add(edge.GetDirEdge(0));
			this.Add(edge.GetDirEdge(1));
		}

		protected void Add(DirectedEdge dirEdge)
		{
			this.dirEdges.Add(dirEdge);
		}

		public IEnumerator<Node> GetNodeEnumerator()
		{
			return this.nodeMap.GetEnumerator();
		}

		public ICollection<Node> Nodes
		{
			get
			{
				return this.nodeMap.Values;
			}
		}

		public IEnumerator<DirectedEdge> GetDirEdgeEnumerator()
		{
			return this.dirEdges.GetEnumerator();
		}

		public IEnumerator<Edge> GetEdgeEnumerator()
		{
			return this._edges.GetEnumerator();
		}

		public IList<Edge> Edges
		{
			get
			{
				return this._edges;
			}
			protected set
			{
				this._edges = value;
			}
		}

		public void Remove(Edge edge)
		{
			this.Remove(edge.GetDirEdge(0));
			this.Remove(edge.GetDirEdge(1));
			this._edges.Remove(edge);
			edge.Remove();
		}

		public void Remove(DirectedEdge de)
		{
			DirectedEdge sym = de.Sym;
			if (sym != null)
			{
				sym.Sym = null;
			}
			de.FromNode.Remove(de);
			de.Remove();
			this.dirEdges.Remove(de);
		}

		public void Remove(Node node)
		{
			foreach (DirectedEdge directedEdge in node.OutEdges.Edges)
			{
				DirectedEdge sym = directedEdge.Sym;
				if (sym != null)
				{
					this.Remove(sym);
				}
				this.dirEdges.Remove(directedEdge);
				Edge edge = directedEdge.Edge;
				if (edge != null)
				{
					this._edges.Remove(edge);
				}
			}
			this.nodeMap.Remove(node.Coordinate);
			node.Remove();
		}

		public IList<Node> FindNodesOfDegree(int degree)
		{
			IList<Node> list = new List<Node>();
			foreach (Node node in this.nodeMap.Values)
			{
				if (node.Degree == degree)
				{
					list.Add(node);
				}
			}
			return list;
		}

		private IList<Edge> _edges = new List<Edge>();

		protected IList<DirectedEdge> dirEdges = new List<DirectedEdge>();

		protected NodeMap nodeMap = new NodeMap();
	}
}
